package yams.resource.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javafx.util.Callback;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import yams.common.exception.BreezeeException;
import yams.domain.*;
import yams.resource.ICategoryResource;
import yams.resource.JsonCommonResource;
import yams.response.JsonResponse;
import yams.service.ICategoryService;
import yams.service.ICommonService;
import yams.service.ISkuService;
import yams.service.impl.DefaultCommonService;
import yams.utils.SystemTool;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

/**
 * 资产类别树资源
 * Created by Silence on 2016/11/3.
 */
@SuppressWarnings("unchecked")
@RestController
@RequestMapping("/category")
public class DefaultCategoryResource extends JsonCommonResource implements ICategoryResource {

    @Resource
    private ICategoryService categoryService;

    @Resource
    private ObjectMapper objectMapper;

    private ICommonService attributeService;

    private ICommonService productService;

    @Resource
    private ISkuService skuService;

    @Override
    public JsonResponse<CategoryEntity> page(CategoryEntity categoryEntity) {
        return null;
    }

    @Override
    public JsonResponse<CategoryEntity> findById(String id) {
        return null;
    }

    @Override
    public JsonResponse<CategoryEntity> findByCode(String code) {
        return null;
    }

    @RequestMapping(value = "/", method = RequestMethod.PUT)
    @Override
    public JsonResponse<CategoryEntity> save(@RequestBody CategoryEntity categoryEntity) {
        return _saveInfo(categoryService, categoryEntity);
    }

    @Override
    public JsonResponse<CategoryEntity> delete(String id) {
        return null;
    }

    @RequestMapping(value = "/tree/{parentId}", method = RequestMethod.GET)
    @Override
    public JsonResponse<CategoryEntity> categoryTree(@PathVariable String parentId) {
        try {
            return JsonResponse.build(categoryService.findCategoryByParentId(parentId));
        } catch (BreezeeException e) {
            e.printStackTrace();
            return JsonResponse.ERROR(e.getMessage());
        }
    }

    @RequestMapping(value = "/attr/", method = RequestMethod.POST)
    @Override
    public JsonResponse<AttributeEntity> pageAttr(@RequestBody AttributeEntity attr) {
        return _pageAll(attributeService, attr);
    }

    @RequestMapping(value = "/attr/", method = RequestMethod.PUT)
    @Override
    public JsonResponse<AttributeEntity> saveAttr(@RequestBody AttributeEntity attr) {
        return _saveInfo(attributeService, attr, new Callback<AttributeEntity, Object>() {
            @Override
            public Object call(AttributeEntity param) {
                if (param.getArgumentsJson() != null && param.getArgumentsJson().size() > 0) {
                    try {
                        param.setArguments(objectMapper.writeValueAsString(param.getArgumentsJson()));
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        });
    }

    @RequestMapping(value = "/attr/{id}", method = RequestMethod.DELETE)
    public JsonResponse<AttributeEntity> delAttr(@PathVariable String id){
        attributeService.deleteById(id);
        return JsonResponse.OK();
    }

    @RequestMapping(value = "/attr/{attrId}", method = RequestMethod.GET)
    @Override
    public JsonResponse<AttributeEntity> findAttrById(@PathVariable String attrId) {
        return _findOne(attributeService, attrId, 0, (Callback<AttributeEntity, Object>) param -> {
            if (StringUtils.hasText(param.getArguments())) {
                try {
                    param.setArgumentsJson(objectMapper.readValue(param.getArguments(), Map.class));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        });
    }

    @RequestMapping(value = "/attr/code/{attrCode}", method = RequestMethod.GET)
    @Override
    public JsonResponse<AttributeEntity> findAttrByCode(@PathVariable String attrCode) {
        return _findOne(attributeService, attrCode, 1, (Callback<AttributeEntity, Object>) param -> {
            if (StringUtils.hasText(param.getArguments())) {
                try {
                    param.setArgumentsJson(objectMapper.readValue(param.getArguments(), Map.class));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        });
    }

    @RequestMapping(value = "/cateAttr/{cateId}", method = RequestMethod.GET)
    @Override
    public JsonResponse<CateAttrEntity> findCateAttr(@PathVariable String cateId) {
        CategoryEntity entity = categoryService.findById(cateId);
        List<CateAttrEntity> l = new ArrayList<>();
        while (entity != null) {
            l.addAll(entity.getCateAttrs());
            entity = entity.getParent();
        }
        l.forEach(a -> {
            try {
                if (a.getAttribute() != null && a.getAttribute().getArguments() != null)
                    a.setArguments(objectMapper.readValue(a.getAttribute().getArguments(), Map.class));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        return JsonResponse.build(l);
    }

    @RequestMapping(value = "/cateAttr/", method = RequestMethod.PUT)
    @Override
    public JsonResponse<CategoryEntity> saveCateAttr(@RequestBody CategoryEntity categoryEntity) {
        CategoryEntity old = categoryService.findById(categoryEntity.getId());
        old.saveAttr(categoryEntity.getCateAttrs(), categoryEntity.getCreateBy());
        return _saveInfo(categoryService, old);
    }

    @RequestMapping(value = "/product/", method = RequestMethod.POST)
    @Override
    public JsonResponse<ProductEntity> pageProduct(@RequestBody ProductEntity product) {
        if(product.getCode()!=null){
            product.getProperties().put("code_like",product.getCode());
        }
        return _pageAll(productService, product);
    }

    @RequestMapping(value = "/product/", method = RequestMethod.PUT)
    @Override
    public JsonResponse<ProductEntity> saveProduct(@RequestBody ProductEntity product) {
        //TODO:如果是修改产品的话，应该先删除属性和sku
        return _saveInfo(productService, product, (Callback<ProductEntity, Object>) param -> {
            SkuEntity self = new SkuEntity();
            self.setProduct(product);
            self.setId(SystemTool.uuid());
            self.setCode(product.getCode());
            self.setName(product.getName());
            self.setCreateBy(product.getCreateBy());
            self.setCreatedDate(new Date());
            self.setModifiedBy(product.getModifiedBy());
            self.setModifiedDate(self.getCreatedDate());
            self.setMyself(true);
            product.setSkus(Collections.singleton(self));
            return null;
        });
    }

    @RequestMapping(value = "/product/{prdId}", method = RequestMethod.GET)
    @Override
    public JsonResponse<ProductEntity> findProductById(@PathVariable String prdId) {
        return _findOne(productService, prdId, 0);
    }

    @RequestMapping(value = "/product/code/{code}", method = RequestMethod.GET)
    @Override
    public JsonResponse<ProductEntity> findProductByCode(@PathVariable String code) {
        return _findOne(productService, code, 1);
    }

    @RequestMapping(value = "/product/sku/{id}", method = RequestMethod.GET)
    @Override
    public JsonResponse<SkuEntity> findSkuByProduct(@PathVariable String id) {
        ProductEntity pe = (ProductEntity) productService.findById(id);
        if (pe != null)
            return JsonResponse.build(pe.getSkus());
        return JsonResponse.OK();
    }

    @RequestMapping(value = "/sku/", method = RequestMethod.POST)
    @Override
    public JsonResponse<SkuEntity> pageSku(@RequestBody SkuEntity sku) {
        if(sku.getHouseId()!=null && sku.getHouseId().equals("-1")) {
            sku.getProperties().put("pageSize", 20);
            sku.getProperties().put("code_like", sku.getCode());
            sku.getProperties().put("house_obj","-1");
        }
        return _pageAll(skuService,sku);
    }

    @Override
    public void initService() {
        if (attributeService == null)
            attributeService = new DefaultCommonService("attributeRepository");
        if (productService == null)
            productService = new DefaultCommonService("productRepository");
    }
}
